<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>AirHead上传文件</title>
    <link rel="stylesheet" type="text/css" href="index.css?v=1">
    <link rel="stylesheet" type="text/css" href="animate.css">
    <link rel="stylesheet" href="filepond.css"  />
    <script type="text/javascript" src="filepond.js"></script>
    <script type="text/javascript" src="vue.global.prod.js"></script>
  </head>
  <body>
    <div id="app">
      <div class="main">
        <div class="tab-btn">
          <button @click="listIsShow = !listIsShow" :style="{backgroundColor:(listIsShow?'orange':'pink'),color:(listIsShow?'#fff':'#666')}">查看{{listIsShow?'消息':'下载'}}</button>
        </div>
        <div class="files" :style="{display:(listIsShow?'block':'none')}">
          <input type="file" class="filepond" name="filepond" multiple>
          <div class="title">
            <i>当前文件总数{{fileList.length}}</i>
            <p>
              <i :class="listIsPreview?'tap':'active'" @click="setListIsPreview(false)">列表模式</i>
              <i :class="listIsPreview?'active':'tap'" @click="setListIsPreview(true)">预览模式</i>
            </p>
          </div>

          <div class="list animate__animated animate__slideInUp" v-if="listIsPreview"> 
            <p v-for="item in fileList">
              <!-- {{item}} -->
              <i class="size">{{item.fSize}}</i>
              <a :href="item.url" target="_blank" v-if="isMedia(item.name) == 'image' || isMedia(item.name) == 'video'">
                <video autoplay controls v-if="isMedia(item.name) == 'video'">
                  <source :src="item.url" type="video/mp4">
                </video>
                <img :src="item.url" v-else>
              </a>
              <a :href="item.url" :download="item.url" v-else>
                <img :src="'/?icon='+item.icon" v-if="item.icon != undefined" style="width:64px;height:64px;">
                <i>{{item.name}}</i>
              </a>
            </p>
          </div>
          <div class="list animate__animated animate__slideInUp" v-else> 
            <p v-for="item in fileList" style="max-width: 100%;width: 100%;display: flex;align-items: center;justify-content: space-between;">
              <a :href="item.url" target="_blank" style="flex-direction: row;justify-content: flex-start;border: 0;padding:3px;">
                <img :src="'/?icon='+item.icon" v-if="item.icon != undefined" style="width: 32px;height: 32px;">
                <i>{{item.name}}</i>
              </a>
              <i style="font-style: normal;color: #666;">{{item.fSize}}</i>
            </p>
          </div>
        </div>
        <div class="msg" @keydown.enter="sendMsg">
          <div class="list">
            <!-- {{msgList}} -->
            <p v-for="item in msgList">
              <!-- <b>{{item.type}}</b> -->
              <span :class="'title '+setMsgClass(item)">
                <i>{{item.user}}</i>
              </span>
              <span :class="'msg '+setMsgClass(item)">
                <a :href="item.data" target="_blank" v-if="item.data.indexOf('http://') == 0 || item.data.indexOf('https://') == 0" class="self-link">{{item.data}}</a>
                <i v-else>{{item.data}}</i>
              </span>
              <span v-if="item.type == 'err' && item.user == 'ws'" style="text-align: center;">
                <i class="re-btn" @click="wsInit">重新连接</i>
              </span>
            </p>
            <i id="chatBottom"></i>
          </div>
          <div class="send">
            <input v-model="inputValue" />
            <button @click="sendMsg">发送</button>
          </div>
        </div> 
      </div>
    </div>
    <div id="tipView" style="display:none;position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9"></div>
    <script type="text/javascript" src="ws.js?v=1"></script>
    <script type="text/javascript" src="config.js"></script>
    <script type="text/javascript">
      const SERVER_URL = server_url || '192.168.6.86:8086'
      let v = Vue
      const app = {
        setup() {
          /*
            websocket消息
           */
          let userIp = v.ref('')
          let msgList = v.ref([])
          function wsInit() {
            let u = `ws://${SERVER_URL}/aardio`
            let n = 'tourist' + String(Date.now()).substring(4, 13)
            ws.open(u,n,(e)=>{
              if (e.type == 'open') {
                ws.onHeart(5000,(e)=>{
                  console.log(e)
                })
                let a = msgList.value
                for(let i in a) {
                  if (a[i].type == 'err' && a[i].user == 'ws') {
                    a.splice(i,1)
                  }
                }
                msgList.value = a
              }
            })
            ws.onClose((e)=>{
              console.log('ws close',e)
              msgShowError('websocket已经断开连接','ws')
            })
            ws.onMsg(async (e)=>{
              // console.log(e)
              let sStr = 'bc,msg,err'
              let d = typeof(e.data)=='string'?JSON.parse(e.data):e.data
              // console.log(d)
              if (d.type == 'online') userIp.value = d.data
              if (sStr.indexOf(d.type) >=0) {
                msgList.value.push(d)
                setTimeout(() => {
                  document.getElementById('chatBottom').scrollIntoView()
                }, 1)
              }
              if (d.user == 'fileup') {
                await getFileList()
              }
            })
          }

          let inputValue = v.ref('')
          async function sendMsg() {
            let s = inputValue.value.trim()
            if (s == '' || s.length <=0) {
              showTip('不能发空信息')
            } else {
              s = s.replace(/"/g, '“')
              s = s.replace(/"/g, '”')
              s = s.replace(/{/g, '｛')
              s = s.replace(/}/g, '｝')
              s = s.replaceAll('(', '（')
              s = s.replaceAll(')', '）')
              s = s.replaceAll('\n', '\\n')
              s = s.replaceAll('\r', '\\r')
              s = s.replaceAll('\t', '\\t')
              ws.send('msg',s,(e)=>{
                // console.log(e)
                inputValue.value = ''
              })
            }
          }

          function setMsgClass(item) {
            let t = item.type
            let u = item.user
            let r = ''
            if (t == 'bc' || t == 'err') r = t
            if (t == 'msg' && userIp.value == u) r = 'self'
            return r
          }

          function msgShowError(d,u) {
            let o = {}
            o.type = 'err'
            o.data = d
            o.user = u
            msgList.value.push(o)
            setTimeout(() => {
              document.getElementById('chatBottom').scrollIntoView()
            }, 1)
          }


          /*
            获取上传文件列表
           */
          let fileList = v.ref([])
          async function getFileList() {
            let url = location.href+'GetFileList'
            // console.log(url)
            const r = await fetch(url);
            if (r.ok) {
              const data = await r.json();
              const d = typeof(data)=='string'?JSON.parse(data):data 
              // console.log(d)
              for (let i in d) {
                let s = d[i].size
                if (s*1 > 1) {
                  if (s < 1024) s = s + 'bit'
                  else if (s < 1024 * 1024) s = (s/1024).toFixed(2) + 'KB'  
                  else if (s < 1024 * 1024 * 1024) s = (s/(1024*1024)).toFixed(2) + 'MB'
                  else if (s < 1024 * 1024 * 1024 * 1024) s = (s/(1024*1024*1024)).toFixed(2) + 'GB'
                }
                d[i].fSize = s
              }
              fileList.value = d
            } else {
              console.error('请求失败，状态码:', r.status);
              if (r.status == 500) {
                showTip('文件上传失败，压缩成rar或zip文件再上传')
              } else {
                showTip('获取文件列表请求失败，状态码:'+r.status)
              }
            }
          }
          //判断是否图片或视频
          function isMedia(n) {
              let r = {}
              let a = n.split('').reverse().join('').split('.')
              let b = a[1].split('/')
              r.name = b[0].split('').reverse().join('')
              r.ext = a[0].split('').reverse().join('')
              const img = 'bmp,png,jpg,jepg,gif'
              const video = 'mp4'
              if (img.indexOf(r.ext) >= 0) return 'image'
                else if (video.indexOf(r.ext) >= 0 ) return 'video'
                  else return r.ext
          }
          // 文件显示模式
          let listIsPreview = v.ref(true)
          function setListIsPreview(t) {
            listIsPreview.value = t
            localStorage.setItem('listIsPreview',t)
          }

          // 小屏幕（ <= 1000px）
          let listIsShow = v.ref(true)
          
          v.onMounted(()=>{
            wsInit()
            getFileList()
            let lip = localStorage.getItem('listIsPreview')
            listIsPreview.value = lip=='true'
          })

          return{
            wsInit,userIp,msgList,inputValue,sendMsg,setMsgClass,
            fileList,getFileList,isMedia,listIsPreview,setListIsPreview,
            listIsShow
          }
        }
      }
      v.createApp(app).mount('#app')

      /*
         文件上传FilePond
       */
      const pageWidth = document.documentElement.clientWidth || document.body.clientWidth
      const btnText = pageWidth > 1000 ? '选择文件或拖拽到此处' : '选择上传文件'
      const maxFiles = 9
      FilePond.registerPlugin(); // 初始化 FilePond
      const inputElement = document.querySelector('input.filepond');
      const pond = FilePond.create(inputElement,{
        //allowImagePreview: true, // 允许预览图片
        //imagePreviewMaxFileSize: '5MB', // 图片预览最大文件大小
        server: '/AirHead/UpLoad/',
        credits: '',   //右下角版权信息,Powered by PQINA那个
        maxFiles: maxFiles,
        allowRevert: true,
        allowRemove: true,
        allowProcess: true,
        // allowBrowse: false,
        labelIdle: `
                      <span class="filepond--label-action" style="display:block;font-size: 18px;">${btnText}</span>
                      <i style="font-style: normal;font-size: 14px;border: 0;">一次最多只能上传<i style="font-size: 20px;color: orange;margin: 0 3px;font-weight: 900;font-style:normal;">${maxFiles}</i>个文件</i>
                    `,
        labelFileProcessing: '上传中...',
        labelFileProcessingComplete: '上传成功',
        labelFileProcessingAborted: '取消上传时使用的标签',
        labelFileProcessingError: '上传失败',  //文件上传过程中出错时使用的标签
        labelFileProcessingRevertError: '在还原文件上传过程中出错时使用的标签',
        labelTapToCancel: '取消上传',
        labelTapToRetry: '重新上传',
        labelTapToUndo: '撤销上传',
      })
      pond.on('warning', (error, file) => { // 监听文件添加事件
        if (error) {
          console.log('Error warning', error);
          if (error.body == 'Max files') showTip(`一次最多只能选择${maxFiles}个文件`)
          return;
        }
        console.log('File warning', file);
      })
      pond.on('addfile', (error, file) => { // 监听文件添加事件
        if (error) {
          console.log('Error adding file', error);
          showTip('选择文件失败'+error)
          return;
        }
        console.log('File added', file);
      })
      pond.on('processfile', (error, file) => { // 监听文件上传成功事件
        if (error) {
          console.log('Error processing file', error);
          // showTip('文件上传失败'+error.type+error.body)
          return;
        }
        console.log('File processed', file);
        setTimeout(() => {
          pond.removeFile(file);
        }, 500); // 隐藏成功提示
      })
      pond.on('removefile', (error,file) => { // 监听文件移除事件
        if (error) {
          console.log('Error removed file', error);
          return;
        }
        console.log('File removed', file);
      })


      /*
        消息提示
       */
      function showTip(s) {
        const tv = document.querySelector('#tipView')
        tv.innerHTML = `
          <div class="animate__animated animate__bounceIn" style="display: flex;flex-direction: column;align-items: center;justify-content: center;width: 100%;height: 20%;background-color: orange">
            <b style="color: #fff;font-size: 220%;">${s}</b>
          </div>`
        tv.style.display = 'block'
        // console.log(tv.innerHTML)
        setTimeout(()=>{
          tv.style.display = 'none'
        },2500)
      }
    </script>
  </body>
</html>

